﻿using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Threading;
using SolidFramework.Pdf;
using SolidFramework.Pdf.Plumbing;

namespace MediaBrowserSL.BLL.Tools
{
    /// <summary>
    /// PDF Tools
    /// </summary>
    public class PDFTools
    {
        private string fileName;
        private string directory;
        private bool isExtract = false;

        /// <summary>
        /// Extract Images From PDF
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="directory"></param>
        public void ExtractImagesFromPDF(string fileName, string directory)
        {
            this.fileName = fileName;
            this.directory = directory;

            //Create Directory
            if (Directory.Exists(directory))
            {
                string[] files = Directory.GetFiles(directory);
                foreach (string file in files)
                    File.Delete(file);
            }
            else
            {
                Directory.CreateDirectory(directory);
            }


            isExtract = true;
            Thread convertThread = new Thread(new ThreadStart(ExtractImage));
            convertThread.SetApartmentState(ApartmentState.STA);
            convertThread.Start();

            while (isExtract)
            {
                Thread.Sleep(10);
            }
        }

        /// <summary>
        /// Extract Image
        /// </summary>
        private void ExtractImage()
        {
            PdfDocument doc = new PdfDocument(fileName);
            doc.Open();

            List<PdfPage> Pages = new List<PdfPage>(doc.Catalog.Pages.PageCount);
            Catalog catalog = (Catalog)SolidFramework.Pdf.Catalog.Create(doc);
            PdfPages pages = (PdfPages)catalog.Pages;

            ProcessPages(ref pages, ref Pages);

            int pageIndex = 0;
            foreach (SolidFramework.Pdf.Plumbing.PdfPage page in Pages)
            {
                // Update the page number.
                pageIndex++;
                CreateImageFromPage(page, 96, directory, Path.GetFileNameWithoutExtension(fileName), pageIndex, "png", ImageFormat.Png);
            }

            isExtract = false;
            doc.Dispose();
        }

        private static void CreateImageFromPage(PdfPage page, int dpi, string directory, string filename, int pageIndex, string extension, ImageFormat format)
        {
            // Create a bitmap from the page with set dpi.
            Bitmap bm = page.DrawBitmap(dpi);

            // Setup the filename.
            string filepath = directory + string.Format(filename + "-{0}.{1}", pageIndex, extension);

            // If the file exits already, delete it. I.E. Overwrite it.
            if (File.Exists(filepath))
                File.Delete(filepath);

            // Save the file.
            bm.Save(filepath, format);

            // Cleanup.
            bm.Dispose();
        }

        private static void ProcessPages(ref PdfPages pages, ref List<PdfPage> listPages)
        {
            // Walk the Pages catalog and get all the page objects.  This will follow 
            // the references and get the actual object that we can work 
            // with recursively.
            foreach (PdfItem pdfItem in pages.Kids)
            {
                PdfDictionary dictionary =
                    (SolidFramework.Pdf.Plumbing.PdfDictionary)
                    SolidFramework.Pdf.Plumbing.PdfItem.GetIndirectionItem(pdfItem);
                if (dictionary.Type == "Pages")
                {
                    SolidFramework.Pdf.Plumbing.PdfPages nodePages =
                        (SolidFramework.Pdf.Plumbing.PdfPages)dictionary;
                    ProcessPages(ref nodePages, ref listPages);
                }
                else if (dictionary.Type == "Page")
                {
                    SolidFramework.Pdf.Plumbing.PdfPage page =
                        (SolidFramework.Pdf.Plumbing.PdfPage)dictionary;
                    listPages.Add(page);
                }
            }
        }

    }
}
